package ALBasicServer.ALProcess.SynTask;

import ALBasicCommon.ALBasicCommonFun;
import ALBasicServer.ALProcess._IALProcessAction;
import ALBasicServer.ALProcess._IALProcessMonitor;
import ALServerLog.ALServerLog;

/**********************
 * 步骤管理器中，专门给Action进行处理并对过程进行监控的任务对象
 * @author mj
 *
 */
public class ALProcessStepActionMonoTask extends _AALProcessBasicMonoTask
{
    //执行回调
    private _IALProcessAction _m_dAction;
    //完成回调
    private _IALProcessAction _m_dDoneAction;
    //失败回调
    private _IALProcessAction _m_dFailAction;
    //失败时停止流程的回调
    private _IALProcessAction _m_dFailStopAction;

    //对应步骤标记
    private String _m_sProcessTag;
    //对应步骤中的任务下标
    private int _m_iProcessTaskIdx;
    //步骤开始执行的时间
    private long _m_lProcessStartTimeMS;
    //超时完成时的监控对象，此对象注意回收和开始的时候都需要置空
    //如果通过task的deal调用，则会默认使用这个参数作为内部步骤处理的监控对象
    private _IALProcessMonitor _m_mTimeoutMonitor;

    public ALProcessStepActionMonoTask(_IALProcessAction _action, String _processTag, int _processTaskIdx, _IALProcessAction _doneDelegate, _IALProcessAction _failDelegate, _IALProcessAction _failStopAction)
    {
        _m_dAction = _action;
        _m_dDoneAction = _doneDelegate;
        _m_dFailAction = _failDelegate;
        _m_dFailStopAction = _failStopAction;

        _m_sProcessTag = _processTag;
        _m_iProcessTaskIdx = _processTaskIdx;
        _m_lProcessStartTimeMS = 0;

        _m_mTimeoutMonitor = null;
    }

    /// <summary>
    /// 内部逻辑中部分脱节情况下可以在通过本函数设置monitor初始值
    /// 以此在task调用的时候设置步骤监控对象的调用方式
    /// </summary>
    @Override
    public void setMonitor(_IALProcessMonitor _monitor)
    {
        _m_mTimeoutMonitor = _monitor;
    }

    @Override
    public void run()
    {
        //设置开始执行时间
        _m_lProcessStartTimeMS = ALBasicCommonFun.getNowTimeMS();

        //获取监控时长
        long monitMaxTimeMS = 0;
        if (null != _m_mTimeoutMonitor)
        {
            monitMaxTimeMS = _m_mTimeoutMonitor.monitorTimeMS(_m_sProcessTag);

            //最多监控100秒
            if (monitMaxTimeMS > 100000)
                monitMaxTimeMS = 100000;
        }

        try
        {
            if(null != _m_dAction)
                _m_dAction.dealAction();

            //计算超出监控的时间
            long timeoutMS = ALBasicCommonFun.getNowTimeMS() - _m_lProcessStartTimeMS - monitMaxTimeMS;
            //已经完成且时间差在1秒以内则不进行处理，这里进行时间判断是为了避免因为计算量过大引起的超时没被捕获
            if (timeoutMS > 500)
            {
                //调用回调
                if (null != _m_mTimeoutMonitor)
                {
                    _m_mTimeoutMonitor.onTimeout(ALBasicCommonFun.getNowTimeMS() - _m_lProcessStartTimeMS, _m_sProcessTag, Integer.toString(_m_iProcessTaskIdx));

                    //如果已经完成需要调用完成的超时处理
                    _m_mTimeoutMonitor.onTimeoutDone(ALBasicCommonFun.getNowTimeMS() - _m_lProcessStartTimeMS, _m_sProcessTag, Integer.toString(_m_iProcessTaskIdx));
                }
            }

            //执行完成后执行完成函数，根据结果判断是否正常
            if (null != _m_dDoneAction)
                _m_dDoneAction.dealAction();
        }
        catch(Exception _ex)
        {
            //调用回调
            if (null != _m_mTimeoutMonitor)
            {
                _m_mTimeoutMonitor.onErr(ALBasicCommonFun.getNowTimeMS() - _m_lProcessStartTimeMS, _m_sProcessTag, Integer.toString(_m_iProcessTaskIdx), _ex);
            }
            else
            {
                ALServerLog.Sys("Multi Process Action " + _m_sProcessTag + " Fail! Task Index: [" + _m_iProcessTaskIdx + "]");
                ALServerLog.Error(_ex.getMessage());
            }

            //执行失败函数
            if(null != _m_dFailAction)
                _m_dFailAction.dealAction();

        	//调用monitor的失败处理函数
            if (null != _m_dFailStopAction)
            	_m_dFailStopAction.dealAction();
            
            ALServerLog.Sys("One Step Action Error!");

            //执行成功函数
            if(null != _m_dDoneAction)
                _m_dDoneAction.dealAction();
        }
        finally
        {
            //释放资源
            discard();
        }
    }

    /// <summary>
    /// 释放本任务对象的相关资源或者关联
    /// </summary>
    public void discard()
    {
        _m_dAction = null;
        _m_dDoneAction = null;
        _m_dFailAction = null;
        
        _m_mTimeoutMonitor = null;
    }
}
